home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_354 / mxmlib / mxmsub.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  14KB  |  634 lines

  1. /* $Revision Header *** Header built automatically - do not edit! ***********
  2.  *
  3.  *    (C) Copyright 1990 by MXM
  4.  *
  5.  *    Name .....: MXMSub.c
  6.  *    Created ..: Saturday 06-Jan-90 23:30
  7.  *    Revision .: 5
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    09-Mar-90    Olsen        Rework for Aztec 5.0
  12.  *    14-Jan-90    Olsen        Renamed to mxm.library
  13.  *    07-Jan-90       Olsen           Added InvertKeyMap
  14.  *    07-Jan-90       Olsen           - Empty log message -
  15.  *    06-Jan-90       Olsen           Created this file!
  16.  *
  17.  * $Revision Header ********************************************************/
  18.  #define REVISION 4
  19.  
  20. VOID
  21. CalcDimensions(cd_String,cd_Width,cd_Height,cd_MaxWidth)
  22. UBYTE *cd_String;
  23. LONG *cd_Width,*cd_Height,cd_MaxWidth;
  24. {
  25.     LONG i,cd_InLine = 0,cd_NumLines = 0;
  26.  
  27.     *cd_Width = *cd_Height = 0;
  28.  
  29.     for(i = 0 ; i < strlen(cd_String) ; i++)
  30.     {
  31.         if(cd_String[i] == '\n' || cd_InLine == cd_MaxWidth)
  32.         {
  33.             if(cd_InLine > *cd_Width)
  34.                 *cd_Width = cd_InLine;
  35.  
  36.             cd_NumLines++;
  37.             cd_InLine = 0;
  38.  
  39.             continue;
  40.         }
  41.  
  42.         if(cd_String[i] == '\33')
  43.         {
  44.             while(cd_String[i] != 'm' && cd_String[i] != 'w' && i < strlen(cd_String))
  45.                 i++;
  46.  
  47.             if(i >= strlen(cd_String))
  48.                 i = strlen(cd_String) - 1;
  49.  
  50.             continue;
  51.         }
  52.  
  53.         if(cd_String[i] < ' ')
  54.             continue;
  55.  
  56.         cd_InLine++;
  57.     }
  58.  
  59.     *cd_Height = cd_NumLines;
  60.  
  61.     if(cd_InLine > *cd_Width)
  62.         *cd_Width = cd_InLine;
  63. }
  64.  
  65. SHORT pop_computestate();
  66. VOID pop_do_highlighting();
  67. VOID pop_render();
  68. VOID pop_draw_menuitem();
  69. struct MenuItem *pop_getitem();
  70. SHORT pop_strlen();
  71.  
  72. #define SETX 2
  73. #define SETY 1
  74.  
  75. /*
  76.  * pop_computestate()
  77.  *
  78.  * This function checks to see where the mouse pointer is in relation to
  79.  * the various menu items in the menu.  If it is inside one of them, it
  80.  * returns which one (indexed by its linear position in the MenuItem list
  81.  * with 0 being the first one).  If not, returns -1.
  82.  *
  83.  * Possible future enhancement: keep a set of state variables containing
  84.  * the UL and LR corners of the last-known select box; this would make
  85.  * a quick check possible and would cut down the computation for short
  86.  * mouse movements (the most common).
  87.  */
  88.  
  89. SHORT
  90. pop_computestate(win, menu)
  91. struct Window *win;
  92. struct Menu *menu;
  93. {
  94.     register SHORT current = 0;
  95.     register SHORT xval, yval;
  96.     register struct MenuItem *item;
  97.  
  98.     /* Get the x and y vals of the mouse position */
  99.  
  100.     xval = win->MouseX - SETX;
  101.     yval = win->MouseY - SETY;
  102.  
  103.     /* If there is a title, decrement the yval by the correct amount */
  104.  
  105.     if(menu->MenuName)
  106.         yval -= POPTITLEHEIGHT;
  107.  
  108.     /* First, see if the pointer is even in the window */
  109.  
  110.     if((xval < 0) || (yval < 0) ||
  111.        (xval > win->Width - SETX) || (yval > win->Height - SETY))
  112.            return(-1);
  113.  
  114.     /* search through the list of menu items, checking the select box  */
  115.     /* of each.  If containment is detected, the job is done.          */
  116.  
  117.     item = menu->FirstItem;
  118.     while(item) {
  119.         if((xval >= item->LeftEdge) && (yval >= item->TopEdge) &&
  120.            (xval <= item->LeftEdge + item->Width) &&
  121.            (yval <= item->TopEdge + item->Height)) {
  122.  
  123.                /* We have found the quarry; now, the result only  */
  124.             /* depends on the MenuItem's ITEMENABLED flag.     */
  125.  
  126.             if(item->Flags & ITEMENABLED)
  127.                    return(current);
  128.             else
  129.                 return(-1);
  130.         }
  131.         current++;
  132.         item = item->NextItem;
  133.     }
  134.  
  135.     /* If the list is exhausted, return the sad news */
  136.  
  137.     return(-1);
  138. }
  139.  
  140. /*
  141.  * pop_highlight()
  142.  *
  143.  * highlight a menu item
  144.  */
  145.  
  146. #define pop_highlight(win, menu, state) pop_do_highlighting(win, menu, state, 0)
  147.  
  148. /*
  149.  * pop_unhighlight()
  150.  *
  151.  * unhighlight a menu item
  152.  */
  153.  
  154. #define pop_unhighlight(win, menu, state) pop_do_highlighting(win, menu, state, 1)
  155.  
  156. /*
  157.  * pop_do_highlighting()
  158.  *
  159.  * Highlight or unhighlight a menu item, given its traversal number.  Assumes
  160.  * this is a rational value -- if it isn't, Watch Out.
  161.  */
  162.  
  163. VOID
  164. pop_do_highlighting(win, menu, state, mode)
  165. struct Window *win;
  166. struct Menu *menu;
  167. SHORT state;
  168. SHORT mode; /* 0 means to highlight, 1 means to unhighlight */
  169. {
  170.     register struct MenuItem *item;
  171.     struct RastPort *rp;
  172.     SHORT offset = 0;
  173.  
  174.     if(menu->MenuName)
  175.         offset = POPTITLEHEIGHT;
  176.  
  177.     /* Get the correct MenuItem structure */
  178.  
  179.     item = pop_getitem(menu, state);
  180.  
  181.     rp = win->RPort;
  182.  
  183.     /* Now, do the highlighting!  The action to be taken depends on    */
  184.     /* the type of highlighting desired for this item.                 */
  185.     /* The way that the flags for highlighting works is truly bizarre  */
  186.  
  187.     if((item->Flags & HIGHNONE) == HIGHNONE)
  188.         return;
  189.  
  190.     if(item->Flags & HIGHCOMP) {
  191.         SetDrMd(rp, COMPLEMENT);
  192.         RectFill(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge +
  193.           offset + SETY), (LONG) (item->LeftEdge + item->Width - 1 + SETX),
  194.           (LONG) (item->TopEdge + item->Height + offset + SETY));
  195.     }
  196.     else if(item->Flags & HIGHBOX) {
  197.         SetDrMd(rp, COMPLEMENT);
  198.         Move(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge + 
  199.           offset + SETY));
  200.  
  201.         Draw(rp, (LONG) (item->LeftEdge + item->Width - 1 + SETX),
  202.           (LONG) (item->TopEdge + offset + SETY));
  203.         Draw(rp, (LONG) (item->LeftEdge + item->Width - 1 + SETX),
  204.           (LONG) (item->TopEdge + item->Height + offset + SETY));
  205.         Move(rp, (LONG) (item->LeftEdge + item->Width - 2 + SETX),
  206.           (LONG) (item->TopEdge + offset + 1 + SETY));
  207.         Draw(rp, (LONG) (item->LeftEdge + item->Width - 2 + SETX),
  208.           (LONG) (item->TopEdge + item->Height + offset + SETY));
  209.  
  210.         Draw(rp, (LONG) item->LeftEdge + SETX,
  211.           (LONG) (item->TopEdge + item->Height + offset + SETY));
  212.         Draw(rp, (LONG) item->LeftEdge + SETX, (LONG) 
  213.           (item->TopEdge + offset + 1 + SETY));
  214.  
  215.         Move(rp, (LONG) item->LeftEdge + 1 + SETX, (LONG) 
  216.           (item->TopEdge + offset + 1 + SETY));
  217.         Draw(rp, (LONG) item->LeftEdge + 1 + SETX,
  218.           (LONG) (item->TopEdge + item->Height + offset - 1 + SETY));
  219.     }
  220.  
  221.     /*  Otherwise, the mode is HIGHIMAGE */
  222.  
  223.     else
  224.         pop_draw_menuitem(win, item, !mode, offset);
  225. }
  226.  
  227. /*
  228.  * pop_render()
  229.  *
  230.  * renders the menu title (if existent) and the menu items
  231.  */
  232.  
  233. VOID
  234. pop_render(win, menu)
  235. struct Window *win;
  236. struct Menu *menu;
  237. {
  238.     struct MenuItem *item;
  239.     struct RastPort *rp;
  240.     SHORT offset = 0;
  241.  
  242.     rp = win->RPort;
  243.  
  244.     /* Fill the background with color 1, like Intuition Menus */
  245.  
  246.     SetAPen(rp, 1L);
  247.     RectFill(rp, 0L + SETX, 0L + SETY, (LONG) win->Width - SETX - 1, (LONG) win->Height - 2 - SETY);
  248.  
  249.     /* First, if there is a Title for this menu, render it in the top */
  250.     /* of the menu.                                                   */
  251.  
  252.     if(menu->MenuName) {
  253.         SetDrMd(rp, JAM1);
  254.         SetAPen(rp, 1L);
  255.         RectFill(rp, 0L, 0L, (LONG) win->Width - 1, (LONG) POPTITLEHEIGHT - 1);
  256.         SetAPen(rp, 0L);
  257.         SetBPen(rp, 1L);
  258.         Move(rp, 4L + SETX, 7L);
  259.         Text(rp, menu->MenuName, (LONG) pop_strlen(menu->MenuName));
  260.         SetDrMd(rp, COMPLEMENT);
  261.         RectFill(rp, 0L, 0L, (LONG) win->Width - 1, (LONG) POPTITLEHEIGHT - 1);
  262.         SetDrMd(rp, JAM1);
  263.         offset = POPTITLEHEIGHT;
  264.         SetAPen(rp, 0);
  265.         Move(rp, 0, POPTITLEHEIGHT);
  266.         Draw(rp, win->Width - 1, POPTITLEHEIGHT);
  267.     }
  268.  
  269.     /* now render all of the menu items */
  270.  
  271.     item = menu->FirstItem;
  272.     while(item) {
  273.         pop_draw_menuitem(win, item, 0, offset);
  274.         item = item->NextItem;
  275.     }
  276. }
  277.  
  278. /*
  279.  * pop_draw_menuitem()
  280.  *
  281.  * Draws the specified menuitem in the given rastport.  The mode argument
  282.  * says what to draw -- 0 means draw the ItemFill, 1 the SelectFill.
  283.  */
  284.  
  285. VOID
  286. pop_draw_menuitem(win, item, mode, offset)
  287. struct Window *win;
  288. struct MenuItem *item;
  289. SHORT mode;
  290. SHORT offset;
  291. {
  292.     /* Area fill patterns */
  293.  
  294.     static USHORT pop_ghost_pattern[] = {
  295.         0x1111, 0x4444
  296.     };
  297.     static USHORT pop_normal_pattern[] = {
  298.         0xffff, 0xffff
  299.     };
  300.  
  301.     APTR fill;
  302.     struct RastPort *rp;
  303.  
  304.     /* first, figure out what to do, and return if it is a NULL thing */
  305.  
  306.     if(!mode)
  307.         fill = item->ItemFill;
  308.     else
  309.         fill = item->SelectFill;
  310.  
  311.     if(!fill)
  312.         return;
  313.  
  314.     rp = win->RPort;
  315.  
  316.     /* First, erase what may already be there, just to be sure that    */
  317.     /* everything works out all right.                                 */
  318.  
  319.     SetAPen(rp, 1L);
  320.     SetDrMd(rp, JAM1);
  321.     RectFill(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge +
  322.       offset + SETY), (LONG) (item->LeftEdge + item->Width + SETX - 1), (LONG)
  323.       (item->TopEdge + item->Height + offset + SETY));
  324.  
  325.     /* If the item is checkmarked, draw the checkmark.  Intuition made */
  326.     /* sure that the CheckMark field of the window structure exists    */
  327.  
  328.     if(item->Flags & CHECKIT)
  329.         if(item->Flags & CHECKED)
  330.             DrawImage(rp, win->CheckMark, (LONG)  item->LeftEdge + SETX,
  331.               (LONG) (item->TopEdge + offset + 1 + SETY));
  332.  
  333.     /* Now, draw the item itself -- depending on the Flag value, it    */
  334.     /* could be either an Image or an IntuiText                        */
  335.  
  336.     if(item->Flags & ITEMTEXT)
  337.         PrintIText(rp, fill, (LONG) item->LeftEdge + SETX, 
  338.           (LONG) (item->TopEdge + offset + SETY));
  339.     else
  340.         DrawImage(rp, fill, (LONG) item->LeftEdge + SETX, 
  341.           (LONG) (item->TopEdge + offset + SETY));
  342.  
  343.     /* If the ITEMENABLED flag is not set, "ghost" the item.           */
  344.  
  345.     if(!(item->Flags & ITEMENABLED)) {
  346.         SetAPen(rp, 1L);
  347.         SetDrMd(rp, JAM1);
  348.         SetAfPt(rp, (USHORT *) pop_ghost_pattern, 1L);
  349.         RectFill(rp, (LONG) item->LeftEdge + SETX, (LONG) (item->TopEdge +
  350.           offset + SETY), (LONG) (item->LeftEdge + item->Width + SETX - 1), (LONG)
  351.           (item->TopEdge + item->Height + offset + SETY));
  352.         SetAfPt(rp, (USHORT *) pop_normal_pattern, 1L);
  353.     }
  354. }
  355.  
  356. /*
  357.  * pop_getitem()
  358.  *
  359.  * given the traversal number of a menu item in a menu (assumes, BTW, that
  360.  * the arguments are valid), return a pointer to the MenuItem structure
  361.  */
  362.  
  363. struct MenuItem *
  364. pop_getitem(menu, which)
  365. struct Menu *menu;
  366. SHORT which;
  367. {
  368.     struct MenuItem *item;
  369.  
  370.     item = menu->FirstItem;
  371.     while(which--)
  372.         item = item->NextItem;
  373.     return(item);
  374. }
  375.  
  376. /*
  377.  * pop_strlen()
  378.  *
  379.  * a home-brewed strlen to prevent it being necessary to hook in whatever
  380.  * huge object file in which the c library's strlen() resides.
  381.  */
  382.  
  383. SHORT
  384. pop_strlen(str)
  385. char *str;
  386. {
  387.     register SHORT count = 0;
  388.  
  389.     for(; *str++; count++);
  390.     return(count);
  391. }
  392.  
  393. #define CONTROLBITS     ( (1 << 5) | (1 << 6) )
  394.  
  395. ULONG
  396. InvertKeyMap(ansicode,ie,km)
  397. ULONG ansicode;
  398. register struct InputEvent *ie;
  399. struct KeyMap *km;
  400. {
  401.     LONG kindex;
  402.     UBYTE code = 0;
  403.  
  404.     ie -> ie_Class        = IECLASS_RAWKEY;
  405.     ie -> ie_EventAddress    = 0;
  406.  
  407.         /* check for codes in (default) high map first  */
  408.  
  409.     switch(ansicode)
  410.     {
  411.         case ' ':    code = 0x40;    /* space            */
  412.                 break;
  413.  
  414.         case 0x08:      code = 0x41;    /* backspace    */
  415.                 break;
  416.  
  417.         case '\t':    code = 0x42;    /* tab                  */
  418.                 break;
  419.  
  420.         case 0x0D:    code = 0x44;    /* return               */
  421.                 break;
  422.  
  423.         case 0x1B:    code = 0x45;    /* esc                  */
  424.                 break;
  425.  
  426.         case 0x7F:    code = 0x46;    /* del                  */
  427.                 break;
  428.     }
  429.  
  430.     ie -> ie_Code        = 0;
  431.     ie -> ie_Qualifier    = 0;
  432.  
  433.     if(code)
  434.     {
  435.         ie -> ie_Code        = code;
  436.         ie -> ie_Qualifier    = 0;
  437.  
  438.         return(TRUE);
  439.     }
  440.  
  441.     LowKeyInvert((UBYTE)ansicode,km,&ie -> ie_Code,&ie -> ie_Qualifier,&kindex);
  442.  
  443.     if(!ie -> ie_Code && !ie -> ie_Qualifier)
  444.         return(FALSE);
  445.  
  446.     return(TRUE);
  447. }
  448.  
  449. #define KEYMAPSIZE      64
  450.  
  451. /* LowKeyInvert returns good code else <0 if no find
  452.  *
  453.  * regarding keymap as many-to-one mapping:
  454.  * -entries for a given key are scanned so that
  455.  *      the minimum number of qualifiers are associated
  456.  *      with the keystroke.
  457.  * -passing a character value of zero corresponds, in
  458.  *      the default keymap, to CTRL-`, which is probably a bug.
  459.  * -numerals are matched with numeric pad keystrokes (no
  460.  *      qualifiers) on standard keymap.  The way to specify
  461.  *      a key on the number row is via its shifted value;
  462.  *      specify explicitly that the qualifier is to be unshifted,
  463.  *      or a "don't care."
  464.  */
  465.  
  466. LowKeyInvert(value,km,codep,qualp,indexp)
  467. register UBYTE value;    /* translation value from low keymap    */
  468. struct KeyMap *km;
  469. UWORD *codep;        /* pointers where answers are to be put */
  470. UWORD *qualp;
  471. ULONG *indexp;        /* dead-key index information (put into ie?)    */
  472. {
  473.     register UWORD code = KEYMAPSIZE - 1;    /* last entry   */
  474.     register unsigned int type;
  475.     register LONG *p;        /* points to four-byte lokeymap entry   */
  476.     int found_it = 0;
  477.  
  478.     *indexp = *qualp = 0;
  479.  
  480.     p = (LONG *)km -> km_LoKeyMap + code;
  481.  
  482.     do
  483.     {
  484.             /* determine type of key        */
  485.  
  486.         if((type = km -> km_LoKeyMapTypes[code]) == KC_VANILLA)
  487.             found_it = CheckVanilla(p,value,qualp);
  488.         else
  489.             if(!(type & KCF_NOP))
  490.                 found_it = CheckNormal(p,value,type,qualp);
  491.  
  492.         --p;
  493.     }
  494.     while(!found_it && code--);
  495.  
  496.     *codep = code;
  497.  
  498.     return(code);
  499. }
  500.  
  501. CheckNormal(four_bytesp, val, type, qualp)
  502. LONG four_bytesp;
  503. UBYTE val;
  504. UWORD type;
  505. UWORD *qualp;
  506. {
  507.     register UBYTE *p = (UBYTE *)four_bytesp; /* codes held in long word  */
  508.     register long position;
  509.  
  510.         /* start with last of four bytes, "more vanilla"        */
  511.  
  512.     p += 3;
  513.  
  514.     for(position = 3 ; position >= 0 ; --position, --p)
  515.     {
  516.         if(*p == val)
  517.         {
  518.             switch(type)
  519.             {
  520.                 case KC_NOQUAL:    if(position != 3)
  521.                             goto NOT_THIS;
  522.  
  523.                         break;
  524.  
  525.                 case KCF_SHIFT:    if(!(position & 2))
  526.                             goto NOT_THIS;
  527.  
  528.                         if(position == 2)
  529.                             *qualp |= IEQUALIFIER_LSHIFT;
  530.  
  531.                         break;
  532.  
  533.                 case KCF_ALT:    if(!(position & 2))
  534.                             goto NOT_THIS;
  535.  
  536.                         if(position == 2)
  537.                             *qualp |= IEQUALIFIER_LALT;
  538.  
  539.                         break;
  540.  
  541.  
  542.                 case KCF_CONTROL:
  543.  
  544.                         if(!(position & 2))
  545.                             goto NOT_THIS;
  546.  
  547.                         if(position == 2)
  548.                             *qualp |= IEQUALIFIER_CONTROL;
  549.  
  550.                         break;
  551.  
  552.                 case KCF_ALT | KCF_CONTROL:
  553.  
  554.                         if(!(position & 1))
  555.                             *qualp |= IEQUALIFIER_LALT;
  556.  
  557.                         if(!(position & 2))
  558.                             *qualp |= IEQUALIFIER_CONTROL;
  559.  
  560.                         break;
  561.  
  562.                 case KCF_SHIFT | KCF_CONTROL:
  563.  
  564.                         if(!(position & 1))
  565.                             *qualp |= IEQUALIFIER_LSHIFT;
  566.  
  567.                         if(!(position & 2))
  568.                             *qualp |= IEQUALIFIER_CONTROL;
  569.  
  570.                         break;
  571.  
  572.  
  573.                 case KCF_SHIFT | KCF_ALT:
  574.  
  575.                         if(!(position & 1))
  576.                             *qualp |= IEQUALIFIER_LSHIFT;
  577.  
  578.                         if(!(position & 2))
  579.                             *qualp |= IEQUALIFIER_LALT;
  580.  
  581.                         break;
  582.  
  583.                 default:    break;
  584.             }
  585.  
  586.             return(TRUE);
  587.         }
  588. NOT_THIS:       ;
  589.     }
  590.  
  591.     return(FALSE);
  592. }
  593.  
  594. CheckVanilla(p,val,qualp)
  595. UBYTE *p;        /* note: byte pointer   */
  596. UBYTE val;
  597. UWORD *qualp;
  598. {
  599.     register int i;
  600.  
  601.         /* only one way to match a vanilla control key  */
  602.  
  603.     if(!(val & CONTROLBITS))
  604.     {
  605.         /* is a control code    */
  606.  
  607.         if((p[3] & ~CONTROLBITS) == val)
  608.         {
  609.             *qualp |= IEQUALIFIER_CONTROL;
  610.             return(TRUE);
  611.         }
  612.     }
  613.     else
  614.     {
  615.         /* not a control        */
  616.  
  617.         for(i = 3 ; i >= 0 ; --i)
  618.         {
  619.             if(p[i] == val)
  620.             {
  621.                 if(!(i & 1))
  622.                     *qualp |= IEQUALIFIER_LSHIFT;
  623.  
  624.                 if(!(i & 2))
  625.                     *qualp |= IEQUALIFIER_LALT;
  626.  
  627.                 return(TRUE);
  628.             }
  629.         }
  630.     }
  631.  
  632.     return(FALSE);
  633. }
  634.